package com.voiceqsologger.service;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.voiceqsologger.config.LlmApiProperties;
import com.voiceqsologger.entity.QsoLog;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.*;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
 * 使用 OpenAI 兼容 Chat Completions 的大模型客户端，将纯文本解析为 QSO 结构。
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class LlmQsoExtractorClient {

    private final LlmApiProperties props;
    private final RestTemplate restTemplate = new RestTemplate();
    private final ObjectMapper mapper = new ObjectMapper();

    /**
     * 解析文本为 QSO 结构（呼号、RST、设备、天线、功率、位置、高度）。
     */
    public QsoLog extract(String transcript) {
        try {
            String apiKey = props.getApiKey();
            if (apiKey == null || apiKey.isEmpty()) apiKey = System.getenv("SILICONFLOW_API_KEY");
            if (apiKey == null || apiKey.isEmpty()) throw new IllegalStateException("未配置 LLM API Key");

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + apiKey);

            String system = "你是业余无线电通联记录解析器。输出严格JSON，字段：callsign, signalReport, rig, antenna, power, height, location。不要输出多余文本。";
            String user = "请从以下文本中抽取业余无线电通联关键信息，未提及的字段置为 null：\n" + transcript;
            String payload = "{" +
                    "\"model\":\"" + props.getModel() + "\"," +
                    "\"messages\":[{" +
                    "\"role\":\"system\",\"content\":\"" + escape(system) + "\"},{" +
                    "\"role\":\"user\",\"content\":\"" + escape(user) + "\"}]," +
                    "\"temperature\":0.2}";

            HttpEntity<String> req = new HttpEntity<>(payload, headers);
            ResponseEntity<String> resp = restTemplate.postForEntity(props.getChatUrl(), req, String.class);
            if (!resp.getStatusCode().is2xxSuccessful()) {
                throw new RuntimeException("LLM 调用失败: code=" + resp.getStatusCodeValue() + ", body=" + resp.getBody());
            }
            String body = resp.getBody();
            String content = parseAssistantContent(body);
            return parseQsoFromJson(content);
        } catch (Exception e) {
            log.error("LLM 解析失败", e);
            return null;
        }
    }

    private String parseAssistantContent(String body) throws Exception {
        JsonNode root = mapper.readTree(body);
        JsonNode choices = root.path("choices");
        if (choices.isArray() && choices.size() > 0) {
            JsonNode msg = choices.get(0).path("message");
            return msg.path("content").asText();
        }
        return null;
    }

    private QsoLog parseQsoFromJson(String jsonText) throws Exception {
        if (jsonText == null || jsonText.isEmpty()) return null;
        JsonNode n = mapper.readTree(jsonText);
        QsoLog log = new QsoLog();
        log.setCallsign(getText(n, "callsign"));
        log.setSignalReport(getText(n, "signalReport"));
        log.setRig(getText(n, "rig"));
        log.setAntenna(getText(n, "antenna"));
        log.setLocation(getText(n, "location"));
        // power/height 将在实体扩展后设置
        return log;
    }

    private static String getText(JsonNode n, String field) {
        JsonNode v = n.get(field);
        if (v == null || v.isNull()) return null;
        return v.asText();
    }

    private static String escape(String s) {
        return s.replace("\\", "\\\\").replace("\"", "\\\"").replace("\n", "\\n");
    }
}



